﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VRacer;
using System.ComponentModel;
using System.Windows.Threading;
using VRacer.Client.Controls;
using System.Windows;
using VRacer.Exceptions;

namespace VRacer
{
    /// <summary>
    /// Obiekt tej klasy jest uzywany do reprezentacji stanu aplikacji. Np. aktualnie toczacej sie gry, ustawien aplikacji.
    /// </summary>
    public class Business : INotifyPropertyChanged
    {
        protected static Business _instance = new Business();

        public static Dispatcher Dispatcher
        {
            get { return App.Current.Dispatcher; }
        }

        public static Business Instance
        {
            get { return _instance; }
        }

        private string _page = @"..\Pages\MainMenu.xaml";
        private Game _game;
        private Settings _settings = new Settings();
        private static DebugTraceListener _debugListener = new DebugTraceListener();

        static Business()
        {
            System.Diagnostics.Debug.Listeners.Add(_debugListener);
            App.Current.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(Current_DispatcherUnhandledException);
        }

        static void Current_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            Exception innerException = e.Exception;
            while (innerException.InnerException != null && !(innerException is IVRacerException))
                innerException = innerException.InnerException;

            Show(innerException);

            e.Handled = true;
        }

        public Settings Settings
        {
            get { return _settings; }
            set { _settings = value; }
        }

        public Game Game
        {
            get { return _game; }
            set
            {
                if (_game != value)
                {
                    if (_game != null)
                        _game.PropertyChanged -= _game_PropertyChanged;

                    _game = value;
                    _game.PropertyChanged += _game_PropertyChanged;
                    OnPropertyChanged("Game");
                    OnPropertyChanged("IsActive");
                    OnPropertyChanged("IsIdle");
                }
            }
        }

        void _game_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "State")
            {
                OnPropertyChanged("IsActive");
                OnPropertyChanged("IsIdle");
            }
        }

        public string Page
        {
            get { return _page; }
            set
            {
                if (_page != value)
                {
                    _page = value;
                    OnPropertyChanged("Page");
                }
            }
        }

        public static void Show(Exception e)
        {
            App.Current.Dispatcher.Invoke((DefaultDelegate)(() =>
                {
                    //jesli zwykly wyjatek lub krytyczny ukryj wszystkie okna
                    if (!(e is IVRacerException) || (e as IVRacerException).Critical)
                    {
                        Window[] windows = new Window[App.Current.Windows.Count];
                        App.Current.Windows.CopyTo(windows, 0);

                        foreach (Window window in windows)
                            window.Hide();

                        var appException = new AppException(e);
                        appException.ShowDialog();
                        App.Current.Shutdown();
                    }
                    else
                    {
                        var appException = new AppException(e);
                        appException.ShowDialog();
                    }
                }));
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string property)
        {
            try
            {

                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
            catch (Exception) { }
        }

        #endregion
    }
}
